home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 001 / pibt40s3.arc / PIBHOSTD.MOD < prev    next >
Encoding:
Text File  |  1987-09-09  |  42.0 KB  |  1,169 lines

  1. (*----------------------------------------------------------------------*)
  2. (*            Do_Host --- Controls execution of host mode               *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Do_Host;
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*     Procedure:  Do_Host                                              *)
  10. (*                                                                      *)
  11. (*     Purpose:    Controls host mode                                   *)
  12. (*                                                                      *)
  13. (*     Calling Sequence:                                                *)
  14. (*                                                                      *)
  15. (*        Do_Host;                                                      *)
  16. (*                                                                      *)
  17. (*      Calls:   Async_Send                                             *)
  18. (*               Async_Receive                                          *)
  19. (*               KeyPressed                                             *)
  20. (*               Clear_Window                                           *)
  21. (*                                                                      *)
  22. (*----------------------------------------------------------------------*)
  23.  
  24. VAR
  25.    Done    : BOOLEAN               (* TRUE to exit host mode            *);
  26.    Found   : BOOLEAN               (* TRUE if user name found           *);
  27.    Ch      : CHAR                  (* Character read/written            *);
  28.    S_Ch    : CHAR                  (* Parity_stripped character         *);
  29.    MyPass  : AnyStr                (* Password                          *);
  30.    Try     : INTEGER               (* Number of login attempts          *);
  31.    Back    : BOOLEAN               (* Back from file transfers          *);
  32.    Ierr    : INTEGER               (* I/O error code                    *);
  33.    Keyed_In: BOOLEAN               (* TRUE if character entered at Kbd  *);
  34.  
  35. BEGIN (* Do_Host *)
  36.                                    (* Clear comm line of garbage *)
  37.    Async_Purge_Buffer;
  38.                                    (* Expert mode OFF by default *)
  39.    Expert_On       := FALSE;
  40.                                    (* Assume line feeds not needed *)
  41.    CR_LF_Host      := CHR( CR );
  42.                                    (* Welcome and linefeed check *)
  43.    Done            := FALSE;
  44.                                    (* Current host status *)
  45.    Cur_Host_Status := '';
  46.  
  47.    Host_Send_String_With_CR('PibTerm Version ' + PibTerm_Version);
  48.    Host_Send_String_With_CR(PibTerm_Date);
  49.    Host_Send_String_With_CR('Beginning Remote Communications');
  50.    Host_Send_String_With_CR(' ');
  51.    Host_Send_String_With_CR('Test if line feeds required ...');
  52.  
  53.    REPEAT
  54.  
  55.       Async_Purge_Buffer;
  56.  
  57.       Host_Send_String_With_CR(' ');
  58.       Host_Send_String_And_Echo('Are these lines O V E R P R I N T I N G ?');
  59.  
  60.       Keyed_In := FALSE;
  61.  
  62.       REPEAT
  63.       UNTIL Async_Receive( Ch ) OR KeyPressed OR ( NOT Host_Carrier_Detect );
  64.  
  65.       S_Ch := CHR( ORD( Ch ) AND $7F );
  66.  
  67.                                    (* Look for keyboard input if any *)
  68.       IF KeyPressed THEN
  69.          BEGIN
  70.             Keyed_In := TRUE;
  71.             READ( KBD, S_Ch );
  72.             IF ( S_Ch = CHR( ESC ) ) THEN
  73.                IF ( NOT KeyPressed ) THEN
  74.                   BEGIN
  75.                      Done        := TRUE;
  76.                      Really_Done := TRUE;
  77.                   END
  78.                ELSE
  79.                   BEGIN
  80.                      Done := TRUE;
  81.                      WHILE KeyPressed DO
  82.                         READ( Kbd , S_Ch );
  83.                   END;
  84.          END;
  85.                                    (* Alter parity if required *)
  86.  
  87.       IF ( ( S_Ch <> Ch ) AND ( NOT Done ) AND ( NOT Keyed_In ) ) THEN
  88.          BEGIN
  89.  
  90.             IF Parity = 'N' THEN
  91.                BEGIN
  92.                   Parity    := 'E';
  93.                   Data_Bits := 7;
  94.                END
  95.             ELSE
  96.                BEGIN
  97.                   Parity    := 'N';
  98.                   Data_Bits := 8;
  99.                END;
  100.  
  101.             Async_Reset_Port( Comm_Port, Baud_Rate, Parity,
  102.                               Data_Bits, Stop_Bits );
  103.  
  104.             Set_Status_Line_Name( Short_Terminal_Name );
  105.             Write_To_Status_Line( Status_Line_Name, 1 );
  106.  
  107.             WRITELN;
  108.             WRITELN('Communication re-adjusted to parity = ',Parity,
  109.                     ' and data bits = ',Data_Bits);
  110.             WRITELN;
  111.  
  112.          END;
  113.                                    (* Echo character *)
  114.       IF ( NOT Done ) THEN
  115.          BEGIN
  116.  
  117.             S_Ch := UpCase( S_Ch );
  118.  
  119.             Host_Send( S_Ch );
  120.  
  121.             IF Printer_On THEN
  122.                WRITE( Lst , S_Ch );
  123.  
  124.             IF Capture_On THEN
  125.                WRITE( Capture_File , S_Ch );
  126.  
  127.          END;
  128.  
  129.       Done := Done OR ( NOT Host_Carrier_Detect );
  130.  
  131.    UNTIL ( S_Ch IN ['Y','N'] ) OR Done;
  132.  
  133.    IF Done THEN Exit;
  134.  
  135.    IF S_Ch = 'Y' THEN
  136.       CR_LF_Host := CHR( CR ) + CHR( LF )
  137.    ELSE
  138.       CR_LF_Host := CHR( CR );
  139.                                    (* Get user's ID and password *)
  140.    Try := 0;
  141.  
  142.    REPEAT
  143.        Try := Try + 1;
  144.        Get_UserInfo( Found );
  145.    UNTIL( ( Try > Max_Login_Try ) OR Found );
  146.  
  147.                                    (* Check for bad logon or carrier drop *)
  148.  
  149.    Done := Done OR ( NOT Found ) OR ( NOT Host_Carrier_Detect );
  150.  
  151.                                    (* Continue to main menu if OK *)
  152.    IF ( NOT Done ) THEN
  153.       BEGIN
  154.                                    (* Mark this as first entry here  *)
  155.          Host_Section := 'I';
  156.                                    (* Loop over main menu until done *)
  157.          REPEAT
  158.  
  159.             CASE Host_Section OF
  160.                'G':  Gossip_Mode;
  161.                'F':  REPEAT
  162.                         Process_File_Transfer_Commands( Done, Back );
  163.                      UNTIL( Done OR Back );
  164.                'D':  IF ( Privilege = 'S' ) THEN
  165.                         BEGIN
  166.                            IF ( NOT Local_Host ) THEN
  167.                               Jump_To_Dos
  168.                            ELSE
  169.                               BEGIN
  170.                                  DosJump('');
  171.                                  Host_Section := Last_Host_Sect;
  172.                               END;
  173.                         END;
  174.                ELSE
  175.                      Process_Host_Commands( Done );
  176.             END (* CASE *);
  177.  
  178.             Done := Done OR ( NOT Host_Carrier_Detect );
  179.  
  180.          UNTIL ( Done );
  181.  
  182.       END;
  183.                                    (* Update status line *)
  184.    Host_Status( 'Wait for call' );
  185.  
  186.                                    (* Record this logout *)
  187.  
  188.    Write_Log( 'Logged off.', FALSE, FALSE );
  189.  
  190.    Host_Status('Logged off');
  191.  
  192.    Write_Log( 'Waiting for call.', FALSE, FALSE );
  193.  
  194. END   (* Do_Host *);
  195.  
  196. (*----------------------------------------------------------------------*)
  197. (*          Initialize_Host_Mode --- Initializes host mode              *)
  198. (*----------------------------------------------------------------------*)
  199.  
  200. PROCEDURE Initialize_Host_Mode;
  201.  
  202. (*----------------------------------------------------------------------*)
  203. (*                                                                      *)
  204. (*     Procedure:  Initialize_Host_Mode                                 *)
  205. (*                                                                      *)
  206. (*     Purpose:    Initializes host mode.                               *)
  207. (*                                                                      *)
  208. (*     Calling Sequence:                                                *)
  209. (*                                                                      *)
  210. (*        Initialize_Host_Mode;                                         *)
  211. (*                                                                      *)
  212. (*     Remarks:                                                         *)
  213. (*                                                                      *)
  214. (*       This routine reads the user file into memory and scans the     *)
  215. (*       message file as well.  The asynchronous communications port    *)
  216. (*       is also initialized.                                           *)
  217. (*                                                                      *)
  218. (*----------------------------------------------------------------------*)
  219.  
  220. VAR
  221.    Qerr           : BOOLEAN;
  222.    User_File      : Text_File;
  223.    User_Line      : AnyStr;
  224.    I              : INTEGER;
  225.    Done_Flag      : BOOLEAN;
  226.    Xfer_List_File : Text_File   (* File transfer list file    *);
  227.  
  228. (*----------------------------------------------------------------------*)
  229. (*            Get_A_String --- get string up to specified delimeter     *)
  230. (*----------------------------------------------------------------------*)
  231.  
  232. FUNCTION Get_A_String( S : AnyStr; VAR IS: INTEGER; Delim: CHAR ) : AnyStr;
  233.  
  234. (*----------------------------------------------------------------------*)
  235. (*                                                                      *)
  236. (*     Function:   Get_A_String                                         *)
  237. (*                                                                      *)
  238. (*     Purpose:    Gets string up to specified delimeter.               *)
  239. (*                                                                      *)
  240. (*     Calling Sequence:                                                *)
  241. (*                                                                      *)
  242. (*        D_String := Get_A_String( S : AnyStr; VAR IS: INTEGER;        *)
  243. (*                                  Delim: CHAR ) : AnyStr;             *)
  244. (*                                                                      *)
  245. (*           S        --- string to be scanned                          *)
  246. (*           IS       --- first position in S to be scanned             *)
  247. (*           Delim    --- delimeter character to mark end of string     *)
  248. (*                                                                      *)
  249. (*           D_String --- returns substring of S beginning at IS and    *)
  250. (*                        proceeding up to (but not including) Delim,   *)
  251. (*                        or end of string.                             *)
  252. (*                                                                      *)
  253. (*----------------------------------------------------------------------*)
  254.  
  255. VAR
  256.    T: AnyStr;
  257.  
  258. BEGIN (* Get_A_String *)
  259.  
  260.    T := '';
  261.  
  262.    WHILE ( IS <= LENGTH( S ) ) AND ( S[IS] <> Delim ) DO
  263.       BEGIN
  264.          T  := T + S[IS];
  265.          IS := IS + 1;
  266.       END;
  267.  
  268.    Get_A_String := T;
  269.  
  270. END   (* Get_A_String *);
  271.  
  272. (*----------------------------------------------------------------------*)
  273. (*      Create_XferList_File --- Create file listing downloadable files *)
  274. (*----------------------------------------------------------------------*)
  275.  
  276. PROCEDURE Create_XferList_File;
  277.  
  278. VAR
  279.    File_Entry          : Directory_Record;
  280.    S_File_Name         : STRING[14];
  281.    S_File_Time         : STRING[8];
  282.    S_File_Date         : STRING[8];
  283.    S_File_Size         : REAL;
  284.    Done                : BOOLEAN;
  285.    Dir_Spec            : AnyStr;
  286.    I                   : INTEGER;
  287.    Fs1                 : REAL;
  288.    Fs2                 : REAL;
  289.    Dir_Skip_Entry      : INTEGER;
  290.  
  291. BEGIN (* Create_XferList_File *)
  292.  
  293.                                    (* XFer_List_File already assigned. *)
  294.             (*$I-*)
  295.    REWRITE( XFer_List_File );
  296.             (*$I+*)
  297.  
  298.    IF ( INT24Result <> 0 ) THEN
  299.       BEGIN
  300.          Write_Log('Cannot create PIBTERM.XFR.', FALSE, TRUE);
  301.          WRITELN;
  302.          EXIT;
  303.       END
  304.    ELSE
  305.       IF ( LENGTH( Host_Mode_Download ) = 0 ) THEN
  306.          BEGIN
  307.             Write_Log('Creating empty PIBTERM.XFR.', FALSE, TRUE);
  308.             WRITELN;
  309.             WRITELN( Xfer_List_File , 'No files available for downloading.' );
  310.             EXIT;
  311.          END;
  312.  
  313.    Write_Log('Creating PIBTERM.XFR from directory ' + Host_Mode_Download + '.',
  314.              FALSE, TRUE);
  315.                                    (* Construct directory specification *)
  316.  
  317.    Dir_Spec := Host_Mode_Download + '*.*';
  318.  
  319.    WRITELN( Xfer_List_File ,
  320.             '====================== Files available for downloading =======================');
  321.  
  322.                                    (* Attributes of files to be skipped.  *)
  323.  
  324.    Dir_Skip_Entry := Dir_Attr_Hidden OR Dir_Attr_Subdirectory OR
  325.                      Dir_Attr_Volume_Label OR Dir_Attr_System;
  326.  
  327.                                    (* Get the download directory contents *)
  328.  
  329.    Done  := ( Dir_Find_First_File( Dir_Spec , File_Entry ) <> 0 );
  330.  
  331.    WHILE( NOT Done ) DO
  332.       BEGIN
  333.                                    (* Skip next directory entry if *)
  334.                                    (* hidden or subdirectory.      *)
  335.  
  336.          IF ( ( File_Entry.File_Attr AND Dir_Skip_Entry ) = 0 ) THEN
  337.             BEGIN
  338.                                    (* Get Next Directory Entry *)
  339.                S_File_Name := '';
  340.                I           := 1;
  341.                                    (* Pick up file name *)
  342.  
  343.                WHILE( ( I <= 14 ) AND ( File_Entry.File_Name[I] <> CHR(0) ) ) DO
  344.                   BEGIN
  345.                      S_File_Name := S_File_Name + File_Entry.File_Name[I];
  346.                      I           := SUCC( I );
  347.                   END;
  348.  
  349.                S_File_Name := S_File_Name + DUPL( ' ' , 14 - LENGTH( S_File_Name ) );
  350.  
  351.                                    (* Pick up creation date and time *)
  352.  
  353.                Dir_Convert_Time( File_Entry.File_Time , S_File_Time );
  354.                Dir_Convert_Date( File_Entry.File_Date , S_File_Date );
  355.  
  356.                                    (* Pick up file size *)
  357.  
  358.                Fs1 := File_Entry.File_Size[1];
  359.                Fs2 := File_Entry.File_Size[2];
  360.  
  361.                IF Fs1 < 0 THEN Fs1 := Fs1 + 65536.0;
  362.                IF Fs2 < 0 THEN Fs2 := Fs2 + 65536.0;
  363.  
  364.                S_File_Size     := Fs2 * 65536.0 + Fs1;
  365.  
  366.                                    (* Write entry to xferlist file *)
  367.  
  368.                WRITELN( Xfer_List_File,
  369.                         S_File_Name,     ' ',
  370.                         S_File_Size:8:0, ' ',
  371.                         S_File_Date,     ' ',
  372.                         S_File_Time );
  373.  
  374.             END;
  375.  
  376.          Done := Done OR ( Dir_Find_Next_File( File_Entry ) <> 0 );
  377.  
  378.    END;
  379.  
  380. END    (* Create_XferList_File *);
  381.  
  382. (*----------------------------------------------------------------------*)
  383.  
  384. BEGIN (* Initialize_Host_Mode *)
  385.                                    (* Set termination flags *)
  386.    Host_Mode      := TRUE;
  387.    Done           := FALSE;
  388.    Really_Done    := FALSE;
  389.    First_Time     := TRUE;
  390.                                    (* Save file paths      *)
  391.  
  392.    Save_Upload       := Upload_Dir_Path;
  393.    Save_Download     := Download_Dir_Path;
  394.    Download_Dir_Path := Host_Mode_Upload;
  395.    Upload_Dir_Path   := Host_Mode_Download;
  396.    Save_Review       := Review_On;
  397.    Review_On         := FALSE;
  398.    Save_Logging      := Logging_On;
  399.    Logging_On        := TRUE;
  400.  
  401.                                    (* Open log file *)
  402.  
  403.    Log_File_Open     := Open_For_Append( Log_File,
  404.                                          Log_File_Name, Ierr );
  405.  
  406.                                    (* Clear screen to start     *)
  407.  
  408.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  409.    Clear_Window;
  410.                                    (* Display status lines      *)
  411.  
  412.    Status_Line_Attr    := 16 * ( ForeGround_Color AND 7 ) +
  413.                           BackGround_Color;
  414.    Do_Status_Line      := TRUE;
  415.    Do_Status_Time      := TRUE;
  416.    Current_Status_Time := -1;
  417.  
  418.    User_Line := ' ESC=quit  F1=chat  F2=logout  F3=DOS  F4=undim  F5=caller  CR=start local';
  419.    User_Line := User_Line + DUPL( ' ' , Max_Screen_Col - LENGTH( User_Line ) );
  420.    WriteSXY( User_Line, 1, Max_Screen_Line - 1, Status_Line_Attr );
  421.  
  422.    Short_Terminal_Name := 'Host Mode';
  423.    Set_Status_Line_Name( Short_Terminal_Name );
  424.    Write_To_Status_Line( Status_Line_Name, 1 );
  425.  
  426.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line - 2 );
  427.    GoToXY( 1 , 1 );
  428.  
  429.    Write_Log('Host mode started.', FALSE, FALSE );
  430.  
  431.                                    (* Allocate space for user file entries. *)
  432.    NEW( User_List );
  433.                                    (* Read in the user file *)
  434.  
  435.    ASSIGN( User_File, Home_Dir + 'PIBTERM.USF' );
  436.       (*$I-*)
  437.    RESET ( User_File );
  438.       (*$I+*)
  439.                                    (* User file not present --- prompt *)
  440.                                    (* for single name, password, and   *)
  441.                                    (* privilege level.                 *)
  442.    IF Int24Result <> 0 THEN
  443.       BEGIN
  444.  
  445.          WRITELN(' ');
  446.  
  447.          Write_Log('No user file present, single user mode assumed.',
  448.                    FALSE, TRUE );
  449.  
  450.          WITH User_List^[1] DO
  451.             BEGIN
  452.                WRITE ('Enter first name: ');
  453.                First_Name := '';
  454.                Read_Edited_String( First_Name );
  455.                WRITELN;
  456.                First_Name := Trim( UpperCase( First_Name ) );
  457.                WRITE ('Enter last name:  ');
  458.                Last_Name := '';
  459.                Read_Edited_String( Last_Name );
  460.                WRITELN;
  461.                Last_Name := Trim( UpperCase( Last_Name ) );
  462.                WRITE ('Enter password:   ');
  463.                PassWord := '';
  464.                Read_Edited_String( PassWord );
  465.                WRITELN;
  466.                PassWord := Trim( PassWord );
  467.                IF YesNo('Allow superuser privileges (Y/N)? ') THEN
  468.                   Privilege := 'S'
  469.                ELSE
  470.                   Privilege := 'N';
  471.             END;
  472.  
  473.          WRITELN(' ');
  474.  
  475.          NUsers := 1;
  476.  
  477.       END
  478.    ELSE
  479.       BEGIN
  480.  
  481.          NUsers := 0;
  482.  
  483.          REPEAT
  484.  
  485.             NUsers := NUsers + 1;
  486.  
  487.             READLN( User_File , User_Line );
  488.  
  489.             WITH User_List^[NUsers] DO
  490.                BEGIN
  491.                   I          := 1;
  492.                   First_Name := Trim( UpperCase( Get_A_String( User_Line, I, ';') ) );
  493.                   I          := I + 1;
  494.                   Last_Name  := Trim( UpperCase( Get_A_String( User_Line, I, ';') ) );
  495.                   I          := I + 1;
  496.                   PassWord   := Trim( Get_A_String( User_Line, I, ';') );
  497.                   I          := I + 1;
  498.                   Privilege  := Trim( UpperCase( Get_A_String( User_Line, I, ';') ) );
  499.                   IF ( Privilege <> 'S' ) THEN
  500.                      Privilege := 'N';
  501.                END;
  502.  
  503.             IF ( User_List^[NUsers].First_Name = '' ) THEN
  504.                NUsers := NUsers - 1;
  505.  
  506.          UNTIL ( EOF( User_File ) OR ( NUsers >= MaxUsers ) );
  507.  
  508.          IF ( NUsers = 1 ) THEN
  509.             Write_Log( 'There is 1 user recorded in user file.',
  510.                        FALSE, TRUE)
  511.          ELSE
  512.             Write_Log( 'There are ' + IToS( NUsers ) + ' users recorded in user file.',
  513.                        FALSE, TRUE);
  514.          WRITELN;
  515.  
  516.          IF Debug_Mode THEN
  517.             IF YesNo('Display users (Y/N)? ') THEN
  518.                BEGIN
  519.  
  520.                   WRITELN(' ');
  521.  
  522.                   FOR I := 1 TO NUsers DO
  523.                      WITH User_List^[I] DO
  524.                         BEGIN
  525.                            WRITE( First_Name, ' ', Last_Name, ' ', PassWord );
  526.                            IF Privilege = 'S' THEN
  527.                               WRITE( '*** SuperUser ***' );
  528.                            WRITELN;
  529.                         END;
  530.  
  531.                END
  532.             ELSE
  533.                WRITELN(' ');
  534.  
  535.       END;
  536.                                    (* Close user file              *)
  537.       (*$I-*)
  538.    CLOSE( User_File );
  539.       (*$I+*)
  540.  
  541.    I := INT24Result;
  542.                                    (* Scan message file to see how *)
  543.                                    (* many messages there are      *)
  544.    NMessages := 0;
  545.  
  546.    ASSIGN( Message_File , Home_Dir + 'PIBTERM.MSG' );
  547.       (*$I-*)
  548.    RESET( Message_File );
  549.       (*$I+*)
  550.  
  551.    IF Int24Result <> 0 THEN
  552.       BEGIN
  553.          Write_Log('No messages in message base.', FALSE, TRUE);
  554.          WRITELN;
  555.       END
  556.    ELSE
  557.       REPEAT
  558.  
  559.          READLN( Message_File , Message_Line );
  560.  
  561.          IF COPY( Message_Line, 1, 6 ) = '== End' THEN
  562.             NMessages := NMessages + 1;
  563.  
  564.       UNTIL ( EOF( Message_File ) );
  565.  
  566.    IF ( NMessages > 0 ) THEN
  567.       IF ( NMessages = 1 ) THEN
  568.          BEGIN
  569.             Write_Log('There is 1 message in message base.',
  570.                       FALSE, TRUE);
  571.             WRITELN;
  572.          END
  573.       ELSE
  574.          BEGIN
  575.             Write_Log('There are ' + IToS( NMessages ) + ' messages in message base.',
  576.                       FALSE, TRUE);
  577.             WRITELN;
  578.          END;
  579.  
  580.       (*$I-*)
  581.    CLOSE( Message_File );
  582.       (*$I+*)
  583.  
  584.    I := INT24Result;
  585.                                    (* Create PIBTERM.XFR if needed *)
  586.  
  587.    ASSIGN( XFer_List_File , Home_Dir + 'PIBTERM.XFR' );
  588.       (*$I-*)
  589.    RESET( XFer_List_File );
  590.       (*$I+*)
  591.  
  592.    IF ( Int24Result <> 0 ) THEN
  593.       Create_XferList_File;
  594.  
  595.       (*$I-*)
  596.    CLOSE( Xfer_List_File );
  597.       (*$I+*)
  598.  
  599.    I := INT24Result;
  600.  
  601. END   (* Initialize_Host_Mode *);
  602.  
  603. (*----------------------------------------------------------------------*)
  604. (*             Terminate_Host_Mode --- Terminate host mode              *)
  605. (*----------------------------------------------------------------------*)
  606.  
  607. PROCEDURE Terminate_Host_Mode;
  608.  
  609. (*----------------------------------------------------------------------*)
  610. (*                                                                      *)
  611. (*     Procedure:  Terminate_Host_Mode                                  *)
  612. (*                                                                      *)
  613. (*     Purpose:    Terminates host mode.                                *)
  614. (*                                                                      *)
  615. (*     Calling Sequence:                                                *)
  616. (*                                                                      *)
  617. (*        Terminate_Host_Mode;                                          *)
  618. (*                                                                      *)
  619. (*     Remarks:                                                         *)
  620. (*                                                                      *)
  621. (*       This routine hangs up the phone.                               *)
  622. (*                                                                      *)
  623. (*----------------------------------------------------------------------*)
  624.  
  625. VAR
  626.    Save_Baud : INTEGER;
  627.  
  628. BEGIN (* Terminate_Host_Mode *)
  629.                                    (* Wait a second for output to drain *)
  630.  
  631.    Cur_Host_Status := 'End host session';
  632.  
  633.    Async_Drain_Output_Buffer( One_Second ) ;
  634.  
  635.    IF ( NOT Hard_Wired ) THEN
  636.       BEGIN
  637.                                    (* Reset the port *)
  638.          Reset_The_Port;
  639.  
  640.          Save_Baud := New_Baud;
  641.          Baud_Rate := New_Baud;
  642.                                    (* Hang up the phone *)
  643.          HangUpPhone;
  644.                                    (* Reset the modem   *)
  645.  
  646.          Send_Modem_Command( Modem_Host_UnSet );
  647.  
  648.          Async_Drain_Output_Buffer( Five_Seconds );
  649.  
  650.          Baud_Rate := Save_Baud;
  651.  
  652.          Async_Reset_Port( Comm_Port, Baud_Rate, Parity, Data_Bits, Stop_Bits );
  653.  
  654.          Set_Status_Line_Name( Short_Terminal_Name );
  655.          Write_To_Status_Line( Status_Line_Name, 1 );
  656.  
  657.       END;
  658.  
  659.    WRITELN;
  660.    WRITELN('Host session ended.');
  661.  
  662.    IF Hard_Wired THEN
  663.       Really_Done := Really_Done OR YesNo('Return to terminal emulation mode (Y/N)? ');
  664.  
  665. END   (* Terminate_Host_Mode *);
  666.  
  667. (*----------------------------------------------------------------------*)
  668. (*        Wait_For_Ring --- Wait for phone to ring and answer it        *)
  669. (*----------------------------------------------------------------------*)
  670.  
  671. PROCEDURE Wait_For_Ring( VAR Done: BOOLEAN );
  672.  
  673. (*----------------------------------------------------------------------*)
  674. (*                                                                      *)
  675. (*     Procedure:  Wait_For_Ring                                        *)
  676. (*                                                                      *)
  677. (*     Purpose:    Answers the phone in host mode.                      *)
  678. (*                                                                      *)
  679. (*     Calling Sequence:                                                *)
  680. (*                                                                      *)
  681. (*        Wait_For_Ring( VAR Done : BOOLEAN );                          *)
  682. (*                                                                      *)
  683. (*           Done -- set TRUE if carrier drops or Sysop requests        *)
  684. (*                   host mode termination.                             *)
  685. (*                                                                      *)
  686. (*     Remarks:                                                         *)
  687. (*                                                                      *)
  688. (*       This routine answers the phone and analyzes the modem response *)
  689. (*       in order to set the proper baud rate for communications.       *)
  690. (*                                                                      *)
  691. (*----------------------------------------------------------------------*)
  692.  
  693. VAR
  694.    Qerr       : BOOLEAN;
  695.    Modem_Ans  : AnyStr;
  696.    Ch         : CHAR;
  697.    I          : INTEGER;
  698.    J          : INTEGER;
  699.    MTimeOut   : BOOLEAN;
  700.    Int_Ch     : INTEGER;
  701.    Blanked    : BOOLEAN;
  702.    Local_Save : Saved_Screen_Ptr;
  703.  
  704. (*----------------------------------------------------------------------*)
  705. (*         Host_Baud_Detect --- Detect caller's baud rate from CRs      *)
  706. (*----------------------------------------------------------------------*)
  707.  
  708. PROCEDURE Host_Baud_Detect;
  709.  
  710. (*----------------------------------------------------------------------*)
  711. (*                                                                      *)
  712. (*     Procedure:  Host_Baud_Detect                                     *)
  713. (*                                                                      *)
  714. (*     Purpose:    Detects caller's baud rate from CR entries           *)
  715. (*                                                                      *)
  716. (*     Calling Sequence:                                                *)
  717. (*                                                                      *)
  718. (*        Host_Baud_Detect;                                             *)
  719. (*                                                                      *)
  720. (*     Calls:                                                           *)
  721. (*                                                                      *)
  722. (*        Async_Receive_With_TimeOut                                    *)
  723. (*                                                                      *)
  724. (*     Remarks:                                                         *)
  725. (*                                                                      *)
  726. (*        The initial baud rate is set to 2400 baud.  Then, as the      *)
  727. (*        enters characters, we look at each and alter the baud rate    *)
  728. (*        until something recognizable emerges.                         *)
  729. (*                                                                      *)
  730. (*----------------------------------------------------------------------*)
  731.  
  732. CONST
  733.    Wait_Ch_Time = 1                (* Seconds to wait for a character *);
  734.  
  735.                                    (* Supported host mode baud rates *)
  736.    N_Of_Host_Baud_Rates = 4;
  737.  
  738.    Host_Baud_Rates : ARRAY[1..N_Of_Host_Baud_Rates] OF INTEGER
  739.                      = ( 2400, 1200, 9600, 300 );
  740.  
  741. VAR
  742.    Found_Speed : BOOLEAN;
  743.    IBaud       : INTEGER;
  744.  
  745. (*----------------------------------------------------------------------*)
  746. (*               Try_Baud_Rate --- Try a specified baud rate            *)
  747. (*----------------------------------------------------------------------*)
  748.  
  749. FUNCTION Try_Baud_Rate( Test_Baud_Rate: INTEGER ) : BOOLEAN;
  750.  
  751. VAR
  752.    Stripped_Ch : INTEGER;
  753.    Timed_Out   : BOOLEAN;
  754.    Ch          : INTEGER;
  755.  
  756. BEGIN (* Try_Baud_Rate *)
  757.                                    (* Assume this baud rate fails *)
  758.    Try_Baud_Rate := FALSE;
  759.                                    (* Set port to given baud rate *)
  760.    Baud_Rate     := Test_Baud_Rate;
  761.  
  762.    Async_Reset_Port( Comm_Port, Baud_Rate, Parity, Data_Bits, Stop_Bits );
  763.  
  764.    Set_Status_Line_Name( Short_Terminal_Name );
  765.    Write_To_Status_Line( Status_Line_Name, 1 );
  766.  
  767.                                    (* Wait for a character              *)
  768.  
  769.    Async_Receive_With_TimeOut( Wait_Ch_Time , Ch );
  770.    Timed_Out := ( Ch = TimeOut );
  771.    Async_Clear_Errors;
  772.                                    (* Strip parity bit                 *)
  773.    Stripped_Ch := ( Ch AND $7F );
  774.                                    (* See if it's recognizable as CR   *)
  775.                                    (* or space.  If so, then check     *)
  776.                                    (* the parity.                      *)
  777.    IF ( NOT Timed_Out ) THEN
  778.       IF ( Stripped_Ch = CR     )   OR
  779.          ( Stripped_Ch = ORD(' ') ) THEN
  780.          BEGIN
  781.             Try_Baud_Rate := TRUE;
  782.             IF ( Stripped_Ch <> Ch ) THEN
  783.                BEGIN
  784.  
  785.                   IF Parity = 'N' THEN
  786.                      BEGIN
  787.                         Parity    := 'E';
  788.                         Data_Bits := 7;
  789.                      END
  790.                   ELSE
  791.                      BEGIN
  792.                         Parity    := 'N';
  793.                         Data_Bits := 8;
  794.                      END;
  795.  
  796.                   Async_Reset_Port( Comm_Port, Baud_Rate, Parity,
  797.                                     Data_Bits, Stop_Bits );
  798.  
  799.                   Set_Status_Line_Name( Short_Terminal_Name );
  800.                   Write_To_Status_Line( Status_Line_Name, 1 );
  801.  
  802.                END;
  803.          END;
  804.  
  805. END   (* Try_Baud_Rate *);
  806.  
  807. (*----------------------------------------------------------------------*)
  808.  
  809. BEGIN (* Host_Baud_Detect *)
  810.                                    (* Indicates if speed detected       *)
  811.    Found_Speed := FALSE;
  812.                                    (* Wait for modem messages to appear *)
  813.  
  814.    DELAY( 2 * Tenth_Of_A_Second_Delay );
  815.  
  816.                                    (* Purge the receive buffer          *)
  817.    Async_Purge_Buffer;
  818.                                    (* Loop until speed found            *)
  819.  
  820.    WHILE ( NOT Found_Speed ) AND ( Async_Carrier_Detect ) DO
  821.       BEGIN
  822.  
  823.          IBaud := 0;
  824.                                    (* Try each baud rate in turn        *)
  825.          REPEAT
  826.  
  827.             IBaud       := IBaud + 1;
  828.             Parity      := 'N';
  829.             Data_Bits   := 8;
  830.             Found_Speed := Try_Baud_Rate( Host_Baud_Rates[IBaud] );
  831.  
  832.          UNTIL ( Found_Speed ) OR ( IBaud >= N_Of_Host_Baud_Rates );
  833.  
  834.                                    (* If we found the speed, try   *)
  835.                                    (* getting a second character.  *)
  836.                                    (* If it's not recognizable,    *)
  837.                                    (* then it didn't work.         *)
  838.          IF Found_Speed THEN
  839.             Found_Speed := Try_Baud_Rate( Host_Baud_Rates[IBaud] );
  840.  
  841.                                    (* If we didn't get the speed,  *)
  842.                                    (* flush the buffer before next *)
  843.                                    (* try.                         *)
  844.  
  845.          IF ( NOT Found_Speed ) THEN
  846.             BEGIN
  847.                DELAY( 5 );
  848.                Async_Purge_Buffer;
  849.             END;
  850.  
  851.       END  (* WHILE *);
  852.                                    (* Flush the buffer once more *)
  853.    DELAY( Tenth_Of_A_Second_Delay );
  854.  
  855.    Async_Purge_Buffer;
  856.  
  857.    WRITELN('Communications adjusted to ',Baud_Rate,' baud and parity = ',
  858.            Parity );
  859.  
  860. END    (* Host_Baud_Detect *);
  861.  
  862. (*----------------------------------------------------------------------*)
  863. (*     Host_AutoBaud_Detect --- Detect caller's baud rate from modem    *)
  864. (*----------------------------------------------------------------------*)
  865.  
  866. PROCEDURE Host_AutoBaud_Detect;
  867.  
  868. VAR
  869.    New_Baud:  INTEGER;
  870.  
  871. BEGIN (* Host_AutoBaud_Detect *)
  872.  
  873.    New_Baud := 0;
  874.    J        := POS( Modem_Connect, Modem_Ans ) + LENGTH( Modem_Connect );
  875.  
  876.    FOR I := J TO LENGTH( Modem_Ans ) DO
  877.       IF Modem_Ans[I] IN ['0'..'9'] THEN
  878.          New_Baud := New_Baud * 10 + ORD( Modem_Ans[I] ) - ORD('0');
  879.  
  880.    IF New_Baud = 0 THEN New_Baud := 300;
  881.  
  882.    IF New_Baud > 0 THEN
  883.       BEGIN
  884.  
  885.          Baud_Rate := New_Baud;
  886.  
  887.          Async_Reset_Port( Comm_Port, Baud_Rate, Parity, Data_Bits, Stop_Bits );
  888.  
  889.          Set_Status_Line_Name( Short_Terminal_Name );
  890.          Write_To_Status_Line( Status_Line_Name, 1 );
  891.  
  892.          WRITELN('Communications adjusted to ',Baud_Rate,' baud.');
  893.  
  894.       END;
  895.  
  896. END   (* Host_AutoBaud_Detect *);
  897.  
  898. (*----------------------------------------------------------------------*)
  899.  
  900. BEGIN (* Wait_For_Ring *)
  901.                                    (* Always 8,n,1 to start in host mode *)
  902.    Parity    := 'N';
  903.    Data_Bits := 8;
  904.    Stop_Bits := 1;
  905.    Baud_Rate := Save_H_Baud_Rate;
  906.  
  907.    Async_Reset_Port( Comm_Port, Baud_Rate, Parity, Data_Bits, Stop_Bits );
  908.  
  909.    Set_Status_Line_Name( Short_Terminal_Name );
  910.    Write_To_Status_Line( Status_Line_Name, 1 );
  911.  
  912.                                    (* Set the modem *)
  913.    IF ( NOT Hard_Wired ) THEN
  914.       Send_Modem_Command( Modem_Host_Set );
  915.  
  916.    Async_Drain_Output_Buffer( Five_Seconds );
  917.  
  918.    Async_Purge_Buffer;
  919.                                    (* Indicate wait for call *)
  920.  
  921.    Host_Status( 'Wait for call' );
  922.  
  923.                                    (* Nothing from modem yet *)
  924.    Modem_Ans  := '';
  925.                                    (* Assume remote session  *)
  926.    Local_Host := FALSE;
  927.                                    (* Raise terminal ready   *)
  928.    Async_Term_Ready( TRUE );
  929.                                    (* Not done yet           *)
  930.    Done := FALSE;
  931.                                    (* Display intro blurb    *)
  932.  
  933.    WRITELN('Waiting for phone to ring.');
  934.    WRITELN('Hit ESC key to return to terminal mode.');
  935.    WRITELN('F1 starts/stops chat mode.');
  936.    WRITELN('F2 immediately logs out remote user.');
  937.    WRITELN('F3 jumps to DOS.');
  938.    WRITELN('F4 undims screen afters it has been dimmed.');
  939.    WRITELN('F5 gives name of current caller.');
  940.    WRITELN('Hit any other key to start local host session.');
  941.  
  942.                                    (* Remove any pending input     *)
  943.    Async_Purge_Buffer;
  944.                                    (* Track time in between sessions *)
  945.    Blank_Time := TimeOfDay;
  946.    Blanked    := FALSE;
  947.  
  948.    REPEAT                          (* Wait for ring/carrier detect *)
  949.  
  950.       IF KeyPressed THEN
  951.          BEGIN
  952.             READ( Kbd, Ch );
  953.             IF Ch = CHR( ESC ) THEN
  954.                BEGIN
  955.                   IF KeyPressed THEN
  956.                      BEGIN
  957.                         READ( Kbd, Ch );
  958.                         CASE ORD( Ch ) OF
  959.                            F3: DosJump('');
  960.                            F4: IF Blanked THEN
  961.                                   BEGIN
  962.                                      Blank_Time          := TimeOfDay;
  963.                                      Restore_Screen( Local_Save );
  964.                                      Current_Status_Time := -1;
  965.                                      Do_Status_Time      := TRUE;
  966.                                      Update_Status_Line;
  967.                                      Blanked             := FALSE;
  968.                                   END;
  969.                            ELSE
  970.                               Local_Host := TRUE;
  971.                         END (* CASE *)
  972.                      END  (* KeyPressed *)
  973.                   ELSE
  974.                      Done := TRUE;
  975.                END
  976.             ELSE
  977.                Local_Host := TRUE;
  978.          END
  979.       ELSE
  980.          GiveAwayTime( 2 );
  981.  
  982.       IF ( NOT Blanked ) THEN
  983.          IF ( TimeDiff( Blank_Time , TimeOfDay ) > Host_Mode_Blank_Time ) THEN
  984.             BEGIN
  985.                WRITELN('Blanking the screen ... ');
  986.                DELAY( Three_Second_Delay );
  987.                Save_Screen( Local_Save );
  988.                Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  989.                Clear_Window;
  990.                Blanked := TRUE;
  991.                Do_Status_Time := FALSE;
  992.             END;
  993.  
  994.    UNTIL ( Host_Carrier_Detect ) OR Done OR Local_Host;
  995.  
  996.    IF Blanked THEN
  997.       BEGIN
  998.          Restore_Screen( Local_Save );
  999.          Current_Status_Time := -1;
  1000.          Do_Status_Time      := TRUE;
  1001.          Update_Status_Line;
  1002.       END;
  1003.  
  1004.    IF Done THEN Really_Done := TRUE;
  1005.  
  1006.                                    (* If local host session,   *)
  1007.                                    (* turn off terminal ready  *)
  1008.                                    (* so phone isn't answered. *)
  1009.    IF Local_Host THEN
  1010.       BEGIN
  1011.          WRITELN('Local host session begins ... ');
  1012.          Async_Term_Ready( FALSE );
  1013.          EXIT;
  1014.       END;
  1015.  
  1016.    IF NOT Done THEN
  1017.       BEGIN                        (* Answer the phone *)
  1018.  
  1019.          WRITELN('Answered phone ... ');
  1020.  
  1021.          Host_Status( 'Answered phone' );
  1022.  
  1023. (*---------------------------------------------------------------*)
  1024. (*                                                               *)
  1025. (*       ----- Let the modem answer the phone -----              *)
  1026. (*                                                               *)
  1027. (*       Send_Modem_Command( Modem_Answer );                     *)
  1028. (*                                                               *)
  1029. (*---------------------------------------------------------------*)
  1030.  
  1031.          DELAY( One_Second_Delay );
  1032.  
  1033.                                    (* Collect modem response for *)
  1034.                                    (* later analysis.            *)
  1035.          MTimeOut := FALSE;
  1036.  
  1037.          REPEAT
  1038.  
  1039.             Async_Receive_With_TimeOut( 1 , Int_Ch );
  1040.  
  1041.             IF Int_Ch <> TimeOut THEN
  1042.                BEGIN
  1043.                   Ch := CHR( Int_Ch );
  1044.                   IF Ch IN ['A'..'Z',' ','0'..'9'] THEN
  1045.                      Modem_Ans := Modem_Ans + Ch;
  1046.                   WRITE( Ch );
  1047.                   IF Printer_On THEN
  1048.                      WRITE( Lst , Ch );
  1049.                   IF Capture_On THEN
  1050.                      WRITE( Capture_File , Ch );
  1051.                END
  1052.             ELSE
  1053.                MTimeOut := TRUE;
  1054.  
  1055.          UNTIL ( MTimeOut OR Done );
  1056.  
  1057.                                    (* Find speed for caller's modem. *)
  1058.          IF ( NOT Done ) THEN
  1059.             IF ( NOT Hard_Wired ) THEN
  1060.                IF Host_Auto_Baud THEN
  1061.                   Host_AutoBaud_Detect
  1062.                ELSE
  1063.                   Host_Baud_Detect;
  1064.  
  1065.       END  (* NOT Done *);
  1066.  
  1067.    Done := Done OR ( NOT Host_Carrier_Detect );
  1068.  
  1069. END   (* Wait_For_Ring *);
  1070.  
  1071. (*----------------------------------------------------------------------*)
  1072. (*            Emulate_Host_Mode --- main routine for host mode          *)
  1073. (*----------------------------------------------------------------------*)
  1074.  
  1075. BEGIN (* Emulate_Host_Mode *)
  1076.                                    (* Make sure we want to enter host mode *)
  1077.                                    (* if session in progress.              *)
  1078.    IF Async_Carrier_Detect THEN
  1079.       IF Attended_Mode THEN
  1080.          BEGIN
  1081.             WRITELN;
  1082.             IF ( NOT YesNo('Are you sure you want to enter host mode (Y/N)? ') ) THEN
  1083.                BEGIN
  1084.                   Terminal_To_Emulate := Saved_Gossip_Term;
  1085.                   Host_Mode           := FALSE;
  1086.                   EXIT;
  1087.                END;
  1088.          END;
  1089.                                    (* Save current port settings *)
  1090.    Save_H_Parity     := Parity;
  1091.    Save_H_Data_Bits  := Data_Bits;
  1092.    Save_H_Stop_Bits  := Stop_Bits;
  1093.    Save_H_Baud_Rate  := Baud_Rate;
  1094.  
  1095.                                    (* Initialize host mode *)
  1096.    Initialize_Host_Mode;
  1097.  
  1098.    IF ( NOT Really_Done ) THEN
  1099.       REPEAT
  1100.                                    (* Wait for call *)
  1101.          Wait_For_Ring( Done );
  1102.                                    (* Do a host session *)
  1103.          IF NOT Done THEN Do_Host;
  1104.                                    (* End host session *)
  1105.          Terminate_Host_Mode;
  1106.  
  1107.       UNTIL Really_Done;
  1108.  
  1109.    DISPOSE( User_List );
  1110.  
  1111.    WRITELN(' ');
  1112.    WRITELN('Host mode communications closed down, ');
  1113.    WRITELN('returning to terminal emulation mode. ');
  1114.  
  1115.    Write_Log('Host mode ended.', FALSE, FALSE );
  1116.  
  1117.             (*$I-*)
  1118.    IF Log_File_Open THEN
  1119.       IF ( NOT Save_Logging ) THEN
  1120.          BEGIN
  1121.             CLOSE( Log_File );
  1122.             Log_File_Open := FALSE;
  1123.          END;
  1124.             (*$I+*)
  1125.  
  1126.    Ierr := Int24Result;
  1127.                                    (* Remove status line display *)
  1128.  
  1129.    Window( 1 , 1 , Max_Screen_Col , Max_Screen_Line );
  1130.  
  1131.    GoToXY( 1 , Max_Screen_Line - 1 );
  1132.    ClrEol;
  1133.    GoToXY( 1 , Max_Screen_Line );
  1134.    ClrEol;
  1135.  
  1136.    GoToXY( 1 , Max_Screen_Line - 1 );
  1137.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1138.  
  1139.                                    (* Restore previous file paths    *)
  1140.  
  1141.    Upload_Dir_Path   := Save_Upload;
  1142.    Download_Dir_Path := Save_Download;
  1143.  
  1144.                                    (* Restore previous terminal type *)
  1145.                                    (* or dumb terminal mode if       *)
  1146.                                    (* previous also host mode.       *)
  1147.  
  1148.    IF ( Saved_Gossip_Term = HostMode ) THEN
  1149.       Terminal_To_Emulate := Dumb
  1150.    ELSE
  1151.       Terminal_To_Emulate := Saved_Gossip_Term;
  1152.  
  1153.    Host_Mode           := FALSE;
  1154.    Review_On           := Save_Review;
  1155.    Logging_On          := Save_Logging;
  1156.  
  1157.                                    (* Restore previous port settings *)
  1158.    Parity    := Save_H_Parity;
  1159.    Data_Bits := Save_H_Data_Bits;
  1160.    Stop_Bits := Save_H_Stop_Bits;
  1161.    Baud_Rate := Save_H_Baud_Rate;
  1162.  
  1163.    Async_Reset_Port( Comm_Port, Baud_Rate, Parity, Data_Bits, Stop_Bits );
  1164.  
  1165.    Set_Status_Line_Name( Short_Terminal_Name );
  1166.    Write_To_Status_Line( Status_Line_Name, 1 );
  1167.  
  1168. END   (* Emulate_Host_Mode *);
  1169.